home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / glibc108.zip / glibc108 / time / zic.c < prev   
C/C++ Source or Header  |  1994-02-24  |  44KB  |  1,940 lines

  1. #ifndef lint
  2. #ifndef NOID
  3. static char    elsieid[] = "@(#)zic.c    7.22";
  4. #endif /* !defined NOID */
  5. #endif /* !defined lint */
  6.  
  7. #include "private.h"
  8. #include "tzfile.h"
  9.  
  10. struct rule {
  11.     const char *    r_filename;
  12.     int        r_linenum;
  13.     const char *    r_name;
  14.  
  15.     int        r_loyear;    /* for example, 1986 */
  16.     int        r_hiyear;    /* for example, 1986 */
  17.     const char *    r_yrtype;
  18.  
  19.     int        r_month;    /* 0..11 */
  20.  
  21.     int        r_dycode;    /* see below */
  22.     int        r_dayofmonth;
  23.     int        r_wday;
  24.  
  25.     long        r_tod;        /* time from midnight */
  26.     int        r_todisstd;    /* above is standard time if TRUE */
  27.                     /* or wall clock time if FALSE */
  28.     long        r_stdoff;    /* offset from standard time */
  29.     const char *    r_abbrvar;    /* variable part of abbreviation */
  30.  
  31.     int        r_todo;        /* a rule to do (used in outzone) */
  32.     time_t        r_temp;        /* used in outzone */
  33. };
  34.  
  35. /*
  36. **    r_dycode        r_dayofmonth    r_wday
  37. */
  38.  
  39. #define DC_DOM        0    /* 1..31 */    /* unused */
  40. #define DC_DOWGEQ    1    /* 1..31 */    /* 0..6 (Sun..Sat) */
  41. #define DC_DOWLEQ    2    /* 1..31 */    /* 0..6 (Sun..Sat) */
  42.  
  43. struct zone {
  44.     const char *    z_filename;
  45.     int        z_linenum;
  46.  
  47.     const char *    z_name;
  48.     long        z_gmtoff;
  49.     const char *    z_rule;
  50.     const char *    z_format;
  51.  
  52.     long        z_stdoff;
  53.  
  54.     struct rule *    z_rules;
  55.     int        z_nrules;
  56.  
  57.     struct rule    z_untilrule;
  58.     time_t        z_untiltime;
  59. };
  60.  
  61. extern int    emkdir P((const char * name, int mode));
  62. extern int    getopt P((int argc, char * argv[], const char * options));
  63. extern char *    icatalloc P((char * old, const char * new));
  64. extern char *    icpyalloc P((const char * string));
  65. extern void    ifree P((char * p));
  66. extern char *    imalloc P((int n));
  67. extern char *    irealloc P((char * old, int n));
  68. extern int    link P((const char * fromname, const char * toname));
  69. extern char *    optarg;
  70. extern int    optind;
  71. extern char *    scheck P((const char * string, const char * format));
  72.  
  73. static void    addtt P((time_t starttime, int type));
  74. static int    addtype P((long gmtoff, const char * abbr, int isdst,
  75.                 int ttisstd));
  76. static void    leapadd P((time_t t, int positive, int rolling, int count));
  77. static void    adjleap P((void));
  78. static void    associate P((void));
  79. static int    ciequal P((const char * ap, const char * bp));
  80. static void    convert P((long val, char * buf));
  81. static void    dolink P((const char * fromfile, const char * tofile));
  82. static void    eat P((const char * name, int num));
  83. static void    eats P((const char * name, int num,
  84.             const char * rname, int rnum));
  85. static long    eitol P((int i));
  86. static void    error P((const char * message));
  87. static char **    getfields P((char * buf));
  88. static long    gethms P((const char * string, const char * errstrng,
  89.             int signable));
  90. static void    infile P((const char * filename));
  91. static void    inleap P((char ** fields, int nfields));
  92. static void    inlink P((char ** fields, int nfields));
  93. static void    inrule P((char ** fields, int nfields));
  94. static int    inzcont P((char ** fields, int nfields));
  95. static int    inzone P((char ** fields, int nfields));
  96. static int    inzsub P((char ** fields, int nfields, int iscont));
  97. static int    itsabbr P((const char * abbr, const char * word));
  98. static int    itsdir P((const char * name));
  99. static int    lowerit P((int c));
  100. static char *    memcheck P((char * tocheck));
  101. static int    mkdirs P((char * filename));
  102. static void    newabbr P((const char * abbr));
  103. static long    oadd P((long t1, long t2));
  104. static void    outzone P((const struct zone * zp, int ntzones));
  105. static void    puttzcode P((long code, FILE * fp));
  106. static int    rcomp P((const genericptr_t leftp, const genericptr_t rightp));
  107. static time_t    rpytime P((const struct rule * rp, int wantedy));
  108. static void    rulesub P((struct rule * rp,
  109.             char * loyearp, char * hiyearp,
  110.             char * typep, char * monthp,
  111.             char * dayp, char * timep));
  112. static void    setboundaries P((void));
  113. static time_t    tadd P((time_t t1, long t2));
  114. static void    usage P((void));
  115. static void    writezone P((const char * name));
  116. static int    yearistype P((int year, const char * type));
  117.  
  118. static int        charcnt;
  119. static int        errors;
  120. static const char *    filename;
  121. static int        leapcnt;
  122. static int        linenum;
  123. static int        max_int;
  124. static time_t        max_time;
  125. static int        max_year;
  126. static int        min_int;
  127. static time_t        min_time;
  128. static int        min_year;
  129. static int        noise;
  130. static const char *    rfilename;
  131. static int        rlinenum;
  132. static const char *    progname;
  133. static int        timecnt;
  134. static int        typecnt;
  135. static int        tt_signed;
  136.  
  137. /*
  138. ** Line codes.
  139. */
  140.  
  141. #define LC_RULE        0
  142. #define LC_ZONE        1
  143. #define LC_LINK        2
  144. #define LC_LEAP        3
  145.  
  146. /*
  147. ** Which fields are which on a Zone line.
  148. */
  149.  
  150. #define ZF_NAME        1
  151. #define ZF_GMTOFF    2
  152. #define ZF_RULE        3
  153. #define ZF_FORMAT    4
  154. #define ZF_TILYEAR    5
  155. #define ZF_TILMONTH    6
  156. #define ZF_TILDAY    7
  157. #define ZF_TILTIME    8
  158. #define ZONE_MINFIELDS    5
  159. #define ZONE_MAXFIELDS    9
  160.  
  161. /*
  162. ** Which fields are which on a Zone continuation line.
  163. */
  164.  
  165. #define ZFC_GMTOFF    0
  166. #define ZFC_RULE    1
  167. #define ZFC_FORMAT    2
  168. #define ZFC_TILYEAR    3
  169. #define ZFC_TILMONTH    4
  170. #define ZFC_TILDAY    5
  171. #define ZFC_TILTIME    6
  172. #define ZONEC_MINFIELDS    3
  173. #define ZONEC_MAXFIELDS    7
  174.  
  175. /*
  176. ** Which files are which on a Rule line.
  177. */
  178.  
  179. #define RF_NAME        1
  180. #define RF_LOYEAR    2
  181. #define RF_HIYEAR    3
  182. #define RF_COMMAND    4
  183. #define RF_MONTH    5
  184. #define RF_DAY        6
  185. #define RF_TOD        7
  186. #define RF_STDOFF    8
  187. #define RF_ABBRVAR    9
  188. #define RULE_FIELDS    10
  189.  
  190. /*
  191. ** Which fields are which on a Link line.
  192. */
  193.  
  194. #define LF_FROM        1
  195. #define LF_TO        2
  196. #define LINK_FIELDS    3
  197.  
  198. /*
  199. ** Which fields are which on a Leap line.
  200. */
  201.  
  202. #define LP_YEAR        1
  203. #define LP_MONTH    2
  204. #define LP_DAY        3
  205. #define LP_TIME        4
  206. #define LP_CORR        5
  207. #define LP_ROLL        6
  208. #define LEAP_FIELDS    7
  209.  
  210. /*
  211. ** Year synonyms.
  212. */
  213.  
  214. #define YR_MINIMUM    0
  215. #define YR_MAXIMUM    1
  216. #define YR_ONLY        2
  217.  
  218. static struct rule *    rules;
  219. static int        nrules;    /* number of rules */
  220.  
  221. static struct zone *    zones;
  222. static int        nzones;    /* number of zones */
  223.  
  224. struct link {
  225.     const char *    l_filename;
  226.     int        l_linenum;
  227.     const char *    l_from;
  228.     const char *    l_to;
  229. };
  230.  
  231. static struct link *    links;
  232. static int        nlinks;
  233.  
  234. struct lookup {
  235.     const char *    l_word;
  236.     const int    l_value;
  237. };
  238.  
  239. static struct lookup const *    byword P((const char * string,
  240.                     const struct lookup * lp));
  241.  
  242. static struct lookup const    line_codes[] = {
  243.     { "Rule",    LC_RULE },
  244.     { "Zone",    LC_ZONE },
  245.     { "Link",    LC_LINK },
  246.     { "Leap",    LC_LEAP },
  247.     { NULL,        0}
  248. };
  249.  
  250. static struct lookup const    mon_names[] = {
  251.     { "January",    TM_JANUARY },
  252.     { "February",    TM_FEBRUARY },
  253.     { "March",    TM_MARCH },
  254.     { "April",    TM_APRIL },
  255.     { "May",    TM_MAY },
  256.     { "June",    TM_JUNE },
  257.     { "July",    TM_JULY },
  258.     { "August",    TM_AUGUST },
  259.     { "September",    TM_SEPTEMBER },
  260.     { "October",    TM_OCTOBER },
  261.     { "November",    TM_NOVEMBER },
  262.     { "December",    TM_DECEMBER },
  263.     { NULL,        0 }
  264. };
  265.  
  266. static struct lookup const    wday_names[] = {
  267.     { "Sunday",    TM_SUNDAY },
  268.     { "Monday",    TM_MONDAY },
  269.     { "Tuesday",    TM_TUESDAY },
  270.     { "Wednesday",    TM_WEDNESDAY },
  271.     { "Thursday",    TM_THURSDAY },
  272.     { "Friday",    TM_FRIDAY },
  273.     { "Saturday",    TM_SATURDAY },
  274.     { NULL,        0 }
  275. };
  276.  
  277. static struct lookup const    lasts[] = {
  278.     { "last-Sunday",    TM_SUNDAY },
  279.     { "last-Monday",    TM_MONDAY },
  280.     { "last-Tuesday",    TM_TUESDAY },
  281.     { "last-Wednesday",    TM_WEDNESDAY },
  282.     { "last-Thursday",    TM_THURSDAY },
  283.     { "last-Friday",    TM_FRIDAY },
  284.     { "last-Saturday",    TM_SATURDAY },
  285.     { NULL,            0 }
  286. };
  287.  
  288. static struct lookup const    begin_years[] = {
  289.     { "minimum",    YR_MINIMUM },
  290.     { "maximum",    YR_MAXIMUM },
  291.     { NULL,        0 }
  292. };
  293.  
  294. static struct lookup const    end_years[] = {
  295.     { "minimum",    YR_MINIMUM },
  296.     { "maximum",    YR_MAXIMUM },
  297.     { "only",    YR_ONLY },
  298.     { NULL,        0 }
  299. };
  300.  
  301. static struct lookup const    leap_types[] = {
  302.     { "Rolling",    TRUE },
  303.     { "Stationary",    FALSE },
  304.     { NULL,        0 }
  305. };
  306.  
  307. static const int    len_months[2][MONSPERYEAR] = {
  308.     { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
  309.     { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
  310. };
  311.  
  312. static const int    len_years[2] = {
  313.     DAYSPERNYEAR, DAYSPERLYEAR
  314. };
  315.  
  316. static time_t        ats[TZ_MAX_TIMES];
  317. static unsigned char    types[TZ_MAX_TIMES];
  318. static long        gmtoffs[TZ_MAX_TYPES];
  319. static char        isdsts[TZ_MAX_TYPES];
  320. static unsigned char    abbrinds[TZ_MAX_TYPES];
  321. static char        ttisstds[TZ_MAX_TYPES];
  322. static char        chars[TZ_MAX_CHARS];
  323. static time_t        trans[TZ_MAX_LEAPS];
  324. static long        corr[TZ_MAX_LEAPS];
  325. static char        roll[TZ_MAX_LEAPS];
  326.  
  327. /*
  328. ** Memory allocation.
  329. */
  330.  
  331. static char *
  332. memcheck(ptr)
  333. char * const    ptr;
  334. {
  335.     if (ptr == NULL) {
  336.         (void) perror(progname);
  337.         (void) exit(EXIT_FAILURE);
  338.     }
  339.     return ptr;
  340. }
  341.  
  342. #define emalloc(size)        memcheck(imalloc(size))
  343. #define erealloc(ptr, size)    memcheck(irealloc(ptr, size))
  344. #define ecpyalloc(ptr)        memcheck(icpyalloc(ptr))
  345. #define ecatalloc(oldp, newp)    memcheck(icatalloc(oldp, newp))
  346.  
  347. /*
  348. ** Error handling.
  349. */
  350.  
  351. static void
  352. eats(name, num, rname, rnum)
  353. const char * const    name;
  354. const int        num;
  355. const char * const    rname;
  356. const int        rnum;
  357. {
  358.     filename = name;
  359.     linenum = num;
  360.     rfilename = rname;
  361.     rlinenum = rnum;
  362. }
  363.  
  364. static void
  365. eat(name, num)
  366. const char * const    name;
  367. const int        num;
  368. {
  369.     eats(name, num, (char *) NULL, -1);
  370. }
  371.  
  372. static void
  373. error(string)
  374. const char * const    string;
  375. {
  376.     /*
  377.     ** Match the format of "cc" to allow sh users to
  378.     **     zic ... 2>&1 | error -t "*" -v
  379.     ** on BSD systems.
  380.     */
  381.     (void) fprintf(stderr, "\"%s\", line %d: %s",
  382.         filename, linenum, string);
  383.     if (rfilename != NULL)
  384.         (void) fprintf(stderr, " (rule from \"%s\", line %d)",
  385.             rfilename, rlinenum);
  386.     (void) fprintf(stderr, "\n");
  387.     ++errors;
  388. }
  389.  
  390. static void
  391. usage()
  392. {
  393.     (void) fprintf(stderr,
  394. "%s: usage is %s [ -s ] [ -v ] [ -l localtime ] [ -p posixrules ] [ -d directory ] \n\
  395. \t[ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n",
  396.         progname, progname);
  397.     (void) exit(EXIT_FAILURE);
  398. }
  399.  
  400. static const char *    psxrules;
  401. static const char *    lcltime;
  402. static const char *    directory;
  403. static const char *    leapsec;
  404. static const char *    yitcommand;
  405. static int        sflag = FALSE;
  406.  
  407. int
  408. main(argc, argv)
  409. int    argc;
  410. char *    argv[];
  411. {
  412.     register int    i, j;
  413.     register int    c;
  414.  
  415. #ifdef unix
  416.     (void) umask(umask(022) | 022);
  417. #endif /* defined unix */
  418.     progname = argv[0];
  419.     while ((c = getopt(argc, argv, "d:l:p:L:vsy:")) != EOF)
  420.         switch (c) {
  421.             default:
  422.                 usage();
  423.             case 'd':
  424.                 if (directory == NULL)
  425.                     directory = optarg;
  426.                 else {
  427.                     (void) fprintf(stderr,
  428. "%s: More than one -d option specified\n",
  429.                         progname);
  430.                     (void) exit(EXIT_FAILURE);
  431.                 }
  432.                 break;
  433.             case 'l':
  434.                 if (lcltime == NULL)
  435.                     lcltime = optarg;
  436.                 else {
  437.                     (void) fprintf(stderr,
  438. "%s: More than one -l option specified\n",
  439.                         progname);
  440.                     (void) exit(EXIT_FAILURE);
  441.                 }
  442.                 break;
  443.             case 'p':
  444.                 if (psxrules == NULL)
  445.                     psxrules = optarg;
  446.                 else {
  447.                     (void) fprintf(stderr,
  448. "%s: More than one -p option specified\n",
  449.                         progname);
  450.                     (void) exit(EXIT_FAILURE);
  451.                 }
  452.                 break;
  453.             case 'y':
  454.                 if (yitcommand == NULL)
  455.                     yitcommand = optarg;
  456.                 else {
  457.                     (void) fprintf(stderr,
  458. "%s: More than one -y option specified\n",
  459.                         progname);
  460.                     (void) exit(EXIT_FAILURE);
  461.                 }
  462.                 break;
  463.             case 'L':
  464.                 if (leapsec == NULL)
  465.                     leapsec = optarg;
  466.                 else {
  467.                     (void) fprintf(stderr,
  468. "%s: More than one -L option specified\n",
  469.                         progname);
  470.                     (void) exit(EXIT_FAILURE);
  471.                 }
  472.                 break;
  473.             case 'v':
  474.                 noise = TRUE;
  475.                 break;
  476.             case 's':
  477.                 sflag = TRUE;
  478.                 break;
  479.         }
  480.     if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
  481.         usage();    /* usage message by request */
  482.     if (directory == NULL)
  483.         directory = TZDIR;
  484.     if (yitcommand == NULL)
  485.         yitcommand = "yearistype";
  486.  
  487.     setboundaries();
  488.  
  489.     if (optind < argc && leapsec != NULL) {
  490.         infile(leapsec);
  491.         adjleap();
  492.     }
  493.  
  494.     zones = (struct zone *) emalloc(0);
  495.     rules = (struct rule *) emalloc(0);
  496.     links = (struct link *) emalloc(0);
  497.     for (i = optind; i < argc; ++i)
  498.         infile(argv[i]);
  499.     if (errors)
  500.         (void) exit(EXIT_FAILURE);
  501.     associate();
  502.     for (i = 0; i < nzones; i = j) {
  503.         /*
  504.         ** Find the next non-continuation zone entry.
  505.         */
  506.         for (j = i + 1; j < nzones && zones[j].z_name == NULL; ++j)
  507.             continue;
  508.         outzone(&zones[i], j - i);
  509.     }
  510.     /*
  511.     ** Make links.
  512.     */
  513.     for (i = 0; i < nlinks; ++i)
  514.         dolink(links[i].l_from, links[i].l_to);
  515.     if (lcltime != NULL)
  516.         dolink(lcltime, TZDEFAULT);
  517.     if (psxrules != NULL)
  518.         dolink(psxrules, TZDEFRULES);
  519.     return (errors == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
  520. }
  521.  
  522. static void
  523. dolink(fromfile, tofile)
  524. const char * const    fromfile;
  525. const char * const    tofile;
  526. {
  527.     register char *    fromname;
  528.     register char *    toname;
  529.  
  530.     if (fromfile[0] == '/')
  531.         fromname = fromfile;
  532.     else {
  533.         fromname = ecpyalloc(directory);
  534.         fromname = ecatalloc(fromname, "/");
  535.         fromname = ecatalloc(fromname, fromfile);
  536.     }
  537.     if (tofile[0] == '/')
  538.         toname = tofile;
  539.     else {
  540.         toname = ecpyalloc(directory);
  541.         toname = ecatalloc(toname, "/");
  542.         toname = ecatalloc(toname, tofile);
  543.     }
  544.     /*
  545.     ** We get to be careful here since
  546.     ** there's a fair chance of root running us.
  547.     */
  548.     if (!itsdir(toname))
  549.         (void) remove(toname);
  550.     if (link(fromname, toname) != 0) {
  551.         if (mkdirs(toname) != 0)
  552.             (void) exit(EXIT_FAILURE);
  553.         if (link(fromname, toname) != 0) {
  554.             (void) fprintf(stderr, "%s: Can't link from %s to ",
  555.                 progname, fromname);
  556.             (void) perror(toname);
  557.             (void) exit(EXIT_FAILURE);
  558.         }
  559.     }
  560.     if (fromname != fromfile)
  561.         ifree(fromname);
  562.     if (toname != tofile)
  563.         ifree(toname);
  564. }
  565.  
  566. static void
  567. setboundaries()
  568. {
  569.     register time_t    bit;
  570.     register int bii;
  571.  
  572.     for (bit = 1; bit > 0; bit <<= 1)
  573.         continue;
  574.     if (bit == 0) {        /* time_t is an unsigned type */
  575.         tt_signed = FALSE;
  576.         min_time = 0;
  577.         max_time = ~(time_t) 0;
  578.         if (sflag)
  579.             max_time >>= 1;
  580.     } else {
  581.         tt_signed = TRUE;
  582.         min_time = bit;
  583.         max_time = bit;
  584.         ++max_time;
  585.         max_time = -max_time;
  586.         if (sflag)
  587.             min_time = 0;
  588.     }
  589.     min_year = TM_YEAR_BASE + gmtime(&min_time)->tm_year;
  590.     max_year = TM_YEAR_BASE + gmtime(&max_time)->tm_year;
  591.  
  592.     for (bii = 1; bii > 0; bii <<= 1)
  593.         continue;
  594.     min_int = bii;
  595.     max_int = -1 - bii;
  596. }
  597.  
  598. static int
  599. itsdir(name)
  600. const char * const    name;
  601. {
  602.     register char *    myname;
  603.     register int    accres;
  604.  
  605.     myname = ecpyalloc(name);
  606.     myname = ecatalloc(myname, "/.");
  607.     accres = access(myname, 0);
  608.     ifree(myname);
  609.     return accres == 0;
  610. }
  611.  
  612. /*
  613. ** Associate sets of rules with zones.
  614. */
  615.  
  616. /*
  617. ** Sort by rule name.
  618. */
  619.  
  620. static int
  621. rcomp(cp1, cp2)
  622. const genericptr_t    cp1;
  623. const genericptr_t    cp2;
  624. {
  625.     return strcmp(((struct rule *) cp1)->r_name,
  626.         ((struct rule *) cp2)->r_name);
  627. }
  628.  
  629. static void
  630. associate()
  631. {
  632.     register struct zone *    zp;
  633.     register struct rule *    rp;
  634.     register int        base, out;
  635.     register int        i;
  636.  
  637.     if (nrules != 0)
  638.         (void) qsort((genericptr_t) rules,
  639.             (qsort_size_t) nrules,
  640.             (qsort_size_t) sizeof *rules, rcomp);
  641.     for (i = 0; i < nzones; ++i) {
  642.         zp = &zones[i];
  643.         zp->z_rules = NULL;
  644.         zp->z_nrules = 0;
  645.     }
  646.     for (base = 0; base < nrules; base = out) {
  647.         rp = &rules[base];
  648.         for (out = base + 1; out < nrules; ++out)
  649.             if (strcmp(rp->r_name, rules[out].r_name) != 0)
  650.                 break;
  651.         for (i = 0; i < nzones; ++i) {
  652.             zp = &zones[i];
  653.             if (strcmp(zp->z_rule, rp->r_name) != 0)
  654.                 continue;
  655.             zp->z_rules = rp;
  656.             zp->z_nrules = out - base;
  657.         }
  658.     }
  659.     for (i = 0; i < nzones; ++i) {
  660.         zp = &zones[i];
  661.         if (zp->z_nrules == 0) {
  662.             /*
  663.             ** Maybe we have a local standard time offset.
  664.             */
  665.             eat(zp->z_filename, zp->z_linenum);
  666.             zp->z_stdoff = gethms(zp->z_rule, "unruly zone", TRUE);
  667.             /*
  668.             ** Note, though, that if there's no rule,
  669.             ** a '%s' in the format is a bad thing.
  670.             */
  671.             if (strchr(zp->z_format, '%') != 0)
  672.                 error("%s in ruleless zone");
  673.         }
  674.     }
  675.     if (errors)
  676.         (void) exit(EXIT_FAILURE);
  677. }
  678.  
  679. static void
  680. infile(name)
  681. const char *    name;
  682. {
  683.     register FILE *            fp;
  684.     register char **        fields;
  685.     register char *            cp;
  686.     register const struct lookup *    lp;
  687.     register int            nfields;
  688.     register int            wantcont;
  689.     register int            num;
  690.     char                buf[BUFSIZ];
  691.  
  692.     if (strcmp(name, "-") == 0) {
  693.         name = "standard input";
  694.         fp = stdin;
  695.     } else if ((fp = fopen(name, "r")) == NULL) {
  696.         (void) fprintf(stderr, "%s: Can't open ", progname);
  697.         (void) perror(name);
  698.         (void) exit(EXIT_FAILURE);
  699.     }
  700.     wantcont = FALSE;
  701.     for (num = 1; ; ++num) {
  702.         eat(name, num);
  703.         if (fgets(buf, (int) sizeof buf, fp) != buf)
  704.             break;
  705.         cp = strchr(buf, '\n');
  706.         if (cp == NULL) {
  707.             error("line too long");
  708.             (void) exit(EXIT_FAILURE);
  709.         }
  710.         *cp = '\0';
  711.         fields = getfields(buf);
  712.         nfields = 0;
  713.         while (fields[nfields] != NULL) {
  714.             static char    nada[1];
  715.  
  716.             if (ciequal(fields[nfields], "-"))
  717.                 fields[nfields] = nada;
  718.             ++nfields;
  719.         }
  720.         if (nfields == 0) {
  721.             /* nothing to do */
  722.         } else if (wantcont) {
  723.             wantcont = inzcont(fields, nfields);
  724.         } else {
  725.             lp = byword(fields[0], line_codes);
  726.             if (lp == NULL)
  727.                 error("input line of unknown type");
  728.             else switch ((int) (lp->l_value)) {
  729.                 case LC_RULE:
  730.                     inrule(fields, nfields);
  731.                     wantcont = FALSE;
  732.                     break;
  733.                 case LC_ZONE:
  734.                     wantcont = inzone(fields, nfields);
  735.                     break;
  736.                 case LC_LINK:
  737.                     inlink(fields, nfields);
  738.                     wantcont = FALSE;
  739.                     break;
  740.                 case LC_LEAP:
  741.                     if (name != leapsec)
  742.                         (void) fprintf(stderr,
  743. "%s: Leap line in non leap seconds file %s\n",
  744.                             progname, name);
  745.                     else    inleap(fields, nfields);
  746.                     wantcont = FALSE;
  747.                     break;
  748.                 default:    /* "cannot happen" */
  749.                     (void) fprintf(stderr,
  750. "%s: panic: Invalid l_value %d\n",
  751.                         progname, lp->l_value);
  752.                     (void) exit(EXIT_FAILURE);
  753.             }
  754.         }
  755.         ifree((char *) fields);
  756.     }
  757.     if (ferror(fp)) {
  758.         (void) fprintf(stderr, "%s: Error reading ", progname);
  759.         (void) perror(filename);
  760.         (void) exit(EXIT_FAILURE);
  761.     }
  762.     if (fp != stdin && fclose(fp)) {
  763.         (void) fprintf(stderr, "%s: Error closing ", progname);
  764.         (void) perror(filename);
  765.         (void) exit(EXIT_FAILURE);
  766.     }
  767.     if (wantcont)
  768.         error("expected continuation line not found");
  769. }
  770.  
  771. /*
  772. ** Convert a string of one of the forms
  773. **    h    -h     hh:mm    -hh:mm    hh:mm:ss    -hh:mm:ss
  774. ** into a number of seconds.
  775. ** A null string maps to zero.
  776. ** Call error with errstring and return zero on errors.
  777. */
  778.  
  779. static long
  780. gethms(string, errstring, signable)
  781. const char *        string;
  782. const char * const    errstring;
  783. const int        signable;
  784. {
  785.     int    hh, mm, ss, sign;
  786.  
  787.     if (string == NULL || *string == '\0')
  788.         return 0;
  789.     if (!signable)
  790.         sign = 1;
  791.     else if (*string == '-') {
  792.         sign = -1;
  793.         ++string;
  794.     } else    sign = 1;
  795.     if (sscanf(string, scheck(string, "%d"), &hh) == 1)
  796.         mm = ss = 0;
  797.     else if (sscanf(string, scheck(string, "%d:%d"), &hh, &mm) == 2)
  798.         ss = 0;
  799.     else if (sscanf(string, scheck(string, "%d:%d:%d"),
  800.         &hh, &mm, &ss) != 3) {
  801.             error(errstring);
  802.             return 0;
  803.     }
  804.     if (hh < 0 || hh >= HOURSPERDAY ||
  805.         mm < 0 || mm >= MINSPERHOUR ||
  806.         ss < 0 || ss > SECSPERMIN) {
  807.             error(errstring);
  808.             return 0;
  809.     }
  810.     return eitol(sign) *
  811.         (eitol(hh * MINSPERHOUR + mm) *
  812.         eitol(SECSPERMIN) + eitol(ss));
  813. }
  814.  
  815. static void
  816. inrule(fields, nfields)
  817. register char ** const    fields;
  818. const int        nfields;
  819. {
  820.     static struct rule    r;
  821.  
  822.     if (nfields != RULE_FIELDS) {
  823.         error("wrong number of fields on Rule line");
  824.         return;
  825.     }
  826.     if (*fields[RF_NAME] == '\0') {
  827.         error("nameless rule");
  828.         return;
  829.     }
  830.     r.r_filename = filename;
  831.     r.r_linenum = linenum;
  832.     r.r_stdoff = gethms(fields[RF_STDOFF], "invalid saved time", TRUE);
  833.     rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND],
  834.         fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]);
  835.     r.r_name = ecpyalloc(fields[RF_NAME]);
  836.     r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]);
  837.     rules = (struct rule *) erealloc((char *) rules,
  838.         (int) ((nrules + 1) * sizeof *rules));
  839.     rules[nrules++] = r;
  840. }
  841.  
  842. static int
  843. inzone(fields, nfields)
  844. register char ** const    fields;
  845. const int        nfields;
  846. {
  847.     register int    i;
  848.     static char *    buf;
  849.  
  850.     if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS) {
  851.         error("wrong number of fields on Zone line");
  852.         return FALSE;
  853.     }
  854.     if (strcmp(fields[ZF_NAME], TZDEFAULT) == 0 && lcltime != NULL) {
  855.         buf = erealloc(buf, 132 + strlen(TZDEFAULT));
  856.         (void) sprintf(buf,
  857. "\"Zone %s\" line and -l option are mutually exclusive",
  858.             TZDEFAULT);
  859.         error(buf);
  860.         return FALSE;
  861.     }
  862.     if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL) {
  863.         buf = erealloc(buf, 132 + strlen(TZDEFRULES));
  864.         (void) sprintf(buf,
  865. "\"Zone %s\" line and -p option are mutually exclusive",
  866.             TZDEFRULES);
  867.         error(buf);
  868.         return FALSE;
  869.     }
  870.     for (i = 0; i < nzones; ++i)
  871.         if (zones[i].z_name != NULL &&
  872.             strcmp(zones[i].z_name, fields[ZF_NAME]) == 0) {
  873.                 buf = erealloc(buf, 132 +
  874.                     strlen(fields[ZF_NAME]) +
  875.                     strlen(zones[i].z_filename));
  876.                 (void) sprintf(buf,
  877. "duplicate zone name %s (file \"%s\", line %d)",
  878.                     fields[ZF_NAME],
  879.                     zones[i].z_filename,
  880.                     zones[i].z_linenum);
  881.                 error(buf);
  882.                 return FALSE;
  883.         }
  884.     return inzsub(fields, nfields, FALSE);
  885. }
  886.  
  887. static int
  888. inzcont(fields, nfields)
  889. register char ** const    fields;
  890. const int        nfields;
  891. {
  892.     if (nfields < ZONEC_MINFIELDS || nfields > ZONEC_MAXFIELDS) {
  893.         error("wrong number of fields on Zone continuation line");
  894.         return FALSE;
  895.     }
  896.     return inzsub(fields, nfields, TRUE);
  897. }
  898.  
  899. static int
  900. inzsub(fields, nfields, iscont)
  901. register char ** const    fields;
  902. const int        nfields;
  903. const int        iscont;
  904. {
  905.     register char *        cp;
  906.     static struct zone    z;
  907.     register int        i_gmtoff, i_rule, i_format;
  908.     register int        i_untilyear, i_untilmonth;
  909.     register int        i_untilday, i_untiltime;
  910.     register int        hasuntil;
  911.  
  912.     if (iscont) {
  913.         i_gmtoff = ZFC_GMTOFF;
  914.         i_rule = ZFC_RULE;
  915.         i_format = ZFC_FORMAT;
  916.         i_untilyear = ZFC_TILYEAR;
  917.         i_untilmonth = ZFC_TILMONTH;
  918.         i_untilday = ZFC_TILDAY;
  919.         i_untiltime = ZFC_TILTIME;
  920.         z.z_name = NULL;
  921.     } else {
  922.         i_gmtoff = ZF_GMTOFF;
  923.         i_rule = ZF_RULE;
  924.         i_format = ZF_FORMAT;
  925.         i_untilyear = ZF_TILYEAR;
  926.         i_untilmonth = ZF_TILMONTH;
  927.         i_untilday = ZF_TILDAY;
  928.         i_untiltime = ZF_TILTIME;
  929.         z.z_name = ecpyalloc(fields[ZF_NAME]);
  930.     }
  931.     z.z_filename = filename;
  932.     z.z_linenum = linenum;
  933.     z.z_gmtoff = gethms(fields[i_gmtoff], "invalid GMT offset", TRUE);
  934.     if ((cp = strchr(fields[i_format], '%')) != 0) {
  935.         if (*++cp != 's' || strchr(cp, '%') != 0) {
  936.             error("invalid abbreviation format");
  937.             return FALSE;
  938.         }
  939.     }
  940.     z.z_rule = ecpyalloc(fields[i_rule]);
  941.     z.z_format = ecpyalloc(fields[i_format]);
  942.     hasuntil = nfields > i_untilyear;
  943.     if (hasuntil) {
  944.         z.z_untilrule.r_filename = filename;
  945.         z.z_untilrule.r_linenum = linenum;
  946.         rulesub(&z.z_untilrule,
  947.             fields[i_untilyear],
  948.             "only",
  949.             "",
  950.             (nfields > i_untilmonth) ?
  951.             fields[i_untilmonth] : "Jan",
  952.             (nfields > i_untilday) ? fields[i_untilday] : "1",
  953.             (nfields > i_untiltime) ? fields[i_untiltime] : "0");
  954.         z.z_untiltime = rpytime(&z.z_untilrule,
  955.             z.z_untilrule.r_loyear);
  956.         if (iscont && nzones > 0 &&
  957.             z.z_untiltime > min_time &&
  958.             z.z_untiltime < max_time &&
  959.             zones[nzones - 1].z_untiltime > min_time &&
  960.             zones[nzones - 1].z_untiltime < max_time &&
  961.             zones[nzones - 1].z_untiltime >= z.z_untiltime) {
  962. error("Zone continuation line end time is not after end time of previous line");
  963.                 return FALSE;
  964.         }
  965.     }
  966.     zones = (struct zone *) erealloc((char *) zones,
  967.         (int) ((nzones + 1) * sizeof *zones));
  968.     zones[nzones++] = z;
  969.     /*
  970.     ** If there was an UNTIL field on this line,
  971.     ** there's more information about the zone on the next line.
  972.     */
  973.     return hasuntil;
  974. }
  975.  
  976. static void
  977. inleap(fields, nfields)
  978. register char ** const    fields;
  979. const int        nfields;
  980. {
  981.     register const char *        cp;
  982.     register const struct lookup *    lp;
  983.     register int            i, j;
  984.     int                year, month, day;
  985.     long                dayoff, tod;
  986.     time_t                t;
  987.  
  988.     if (nfields != LEAP_FIELDS) {
  989.         error("wrong number of fields on Leap line");
  990.         return;
  991.     }
  992.     dayoff = 0;
  993.     cp = fields[LP_YEAR];
  994.     if (sscanf(cp, scheck(cp, "%d"), &year) != 1) {
  995.             /*
  996.              * Leapin' Lizards!
  997.              */
  998.             error("invalid leaping year");
  999.             return;
  1000.     }
  1001.     j = EPOCH_YEAR;
  1002.     while (j != year) {
  1003.         if (year > j) {
  1004.             i = len_years[isleap(j)];
  1005.             ++j;
  1006.         } else {
  1007.             --j;
  1008.             i = -len_years[isleap(j)];
  1009.         }
  1010.         dayoff = oadd(dayoff, eitol(i));
  1011.     }
  1012.     if ((lp = byword(fields[LP_MONTH], mon_names)) == NULL) {
  1013.         error("invalid month name");
  1014.         return;
  1015.     }
  1016.     month = lp->l_value;
  1017.     j = TM_JANUARY;
  1018.     while (j != month) {
  1019.         i = len_months[isleap(year)][j];
  1020.         dayoff = oadd(dayoff, eitol(i));
  1021.         ++j;
  1022.     }
  1023.     cp = fields[LP_DAY];
  1024.     if (sscanf(cp, scheck(cp, "%d"), &day) != 1 ||
  1025.         day <= 0 || day > len_months[isleap(year)][month]) {
  1026.             error("invalid day of month");
  1027.             return;
  1028.     }
  1029.     dayoff = oadd(dayoff, eitol(day - 1));
  1030.     if (dayoff < 0 && !tt_signed) {
  1031.         error("time before zero");
  1032.         return;
  1033.     }
  1034.     t = (time_t) dayoff * SECSPERDAY;
  1035.     /*
  1036.     ** Cheap overflow check.
  1037.     */
  1038.     if (t / SECSPERDAY != dayoff) {
  1039.         error("time overflow");
  1040.         return;
  1041.     }
  1042.     tod = gethms(fields[LP_TIME], "invalid time of day", FALSE);
  1043.     cp = fields[LP_CORR];
  1044.     {
  1045.         register int    positive;
  1046.         int        count;
  1047.  
  1048.         if (strcmp(cp, "") == 0) { /* infile() turns "-" into "" */
  1049.             positive = FALSE;
  1050.             count = 1;
  1051.         } else if (strcmp(cp, "--") == 0) {
  1052.             positive = FALSE;
  1053.             count = 2;
  1054.         } else if (strcmp(cp, "+") == 0) {
  1055.             positive = TRUE;
  1056.             count = 1;
  1057.         } else if (strcmp(cp, "++") == 0) {
  1058.             positive = TRUE;
  1059.             count = 2;
  1060.         } else {
  1061.             error("illegal CORRECTION field on Leap line");
  1062.             return;
  1063.         }
  1064.         if ((lp = byword(fields[LP_ROLL], leap_types)) == NULL) {
  1065.             error("illegal Rolling/Stationary field on Leap line");
  1066.             return;
  1067.         }
  1068.         leapadd(tadd(t, tod), positive, lp->l_value, count);
  1069.     }
  1070. }
  1071.  
  1072. static void
  1073. inlink(fields, nfields)
  1074. register char ** const    fields;
  1075. const int        nfields;
  1076. {
  1077.     struct link    l;
  1078.  
  1079.     if (nfields != LINK_FIELDS) {
  1080.         error("wrong number of fields on Link line");
  1081.         return;
  1082.     }
  1083.     if (*fields[LF_FROM] == '\0') {
  1084.         error("blank FROM field on Link line");
  1085.         return;
  1086.     }
  1087.     if (*fields[LF_TO] == '\0') {
  1088.         error("blank TO field on Link line");
  1089.         return;
  1090.     }
  1091.     l.l_filename = filename;
  1092.     l.l_linenum = linenum;
  1093.     l.l_from = ecpyalloc(fields[LF_FROM]);
  1094.     l.l_to = ecpyalloc(fields[LF_TO]);
  1095.     links = (struct link *) erealloc((char *) links,
  1096.         (int) ((nlinks + 1) * sizeof *links));
  1097.     links[nlinks++] = l;
  1098. }
  1099.  
  1100. static void
  1101. rulesub(rp, loyearp, hiyearp, typep, monthp, dayp, timep)
  1102. register struct rule * const    rp;
  1103. char * const            loyearp;
  1104. char * const            hiyearp;
  1105. char * const            typep;
  1106. char * const            monthp;
  1107. char * const            dayp;
  1108. char * const            timep;
  1109. {
  1110.     register struct lookup const *    lp;
  1111.     register char *            cp;
  1112.  
  1113.     if ((lp = byword(monthp, mon_names)) == NULL) {
  1114.         error("invalid month name");
  1115.         return;
  1116.     }
  1117.     rp->r_month = lp->l_value;
  1118.     rp->r_todisstd = FALSE;
  1119.     cp = timep;
  1120.     if (*cp != '\0') {
  1121.         cp += strlen(cp) - 1;
  1122.         switch (lowerit(*cp)) {
  1123.             case 's':
  1124.                 rp->r_todisstd = TRUE;
  1125.                 *cp = '\0';
  1126.                 break;
  1127.             case 'w':
  1128.                 rp->r_todisstd = FALSE;
  1129.                 *cp = '\0';
  1130.                 break;
  1131.         }
  1132.     }
  1133.     rp->r_tod = gethms(timep, "invalid time of day", FALSE);
  1134.     /*
  1135.     ** Year work.
  1136.     */
  1137.     cp = loyearp;
  1138.     if ((lp = byword(cp, begin_years)) != NULL) switch ((int) lp->l_value) {
  1139.         case YR_MINIMUM:
  1140.             rp->r_loyear = min_int;
  1141.             break;
  1142.         case YR_MAXIMUM:
  1143.             rp->r_loyear = max_int;
  1144.             break;
  1145.         default:    /* "cannot happen" */
  1146.             (void) fprintf(stderr,
  1147.                 "%s: panic: Invalid l_value %d\n",
  1148.                 progname, lp->l_value);
  1149.             (void) exit(EXIT_FAILURE);
  1150.     } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_loyear) != 1) {
  1151.         error("invalid starting year");
  1152.         return;
  1153.     }
  1154.     cp = hiyearp;
  1155.     if ((lp = byword(cp, end_years)) != NULL) switch ((int) lp->l_value) {
  1156.         case YR_MINIMUM:
  1157.             rp->r_hiyear = min_int;
  1158.             break;
  1159.         case YR_MAXIMUM:
  1160.             rp->r_hiyear = max_int;
  1161.             break;
  1162.         case YR_ONLY:
  1163.             rp->r_hiyear = rp->r_loyear;
  1164.             break;
  1165.         default:    /* "cannot happen" */
  1166.             (void) fprintf(stderr,
  1167.                 "%s: panic: Invalid l_value %d\n",
  1168.                 progname, lp->l_value);
  1169.             (void) exit(EXIT_FAILURE);
  1170.     } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_hiyear) != 1) {
  1171.         error("invalid ending year");
  1172.         return;
  1173.     }
  1174.     if (rp->r_loyear > rp->r_hiyear) {
  1175.         error("starting year greater than ending year");
  1176.         return;
  1177.     }
  1178.     if (*typep == '\0')
  1179.         rp->r_yrtype = NULL;
  1180.     else {
  1181.         if (rp->r_loyear == rp->r_hiyear) {
  1182.             error("typed single year");
  1183.             return;
  1184.         }
  1185.         rp->r_yrtype = ecpyalloc(typep);
  1186.     }
  1187.     /*
  1188.     ** Day work.
  1189.     ** Accept things such as:
  1190.     **    1
  1191.     **    last-Sunday
  1192.     **    Sun<=20
  1193.     **    Sun>=7
  1194.     */
  1195.     if ((lp = byword(dayp, lasts)) != NULL) {
  1196.         rp->r_dycode = DC_DOWLEQ;
  1197.         rp->r_wday = lp->l_value;
  1198.         rp->r_dayofmonth = len_months[1][rp->r_month];
  1199.     } else {
  1200.         if ((cp = strchr(dayp, '<')) != 0)
  1201.             rp->r_dycode = DC_DOWLEQ;
  1202.         else if ((cp = strchr(dayp, '>')) != 0)
  1203.             rp->r_dycode = DC_DOWGEQ;
  1204.         else {
  1205.             cp = dayp;
  1206.             rp->r_dycode = DC_DOM;
  1207.         }
  1208.         if (rp->r_dycode != DC_DOM) {
  1209.             *cp++ = 0;
  1210.             if (*cp++ != '=') {
  1211.                 error("invalid day of month");
  1212.                 return;
  1213.             }
  1214.             if ((lp = byword(dayp, wday_names)) == NULL) {
  1215.                 error("invalid weekday name");
  1216.                 return;
  1217.             }
  1218.             rp->r_wday = lp->l_value;
  1219.         }
  1220.         if (sscanf(cp, scheck(cp, "%d"), &rp->r_dayofmonth) != 1 ||
  1221.             rp->r_dayofmonth <= 0 ||
  1222.             (rp->r_dayofmonth > len_months[1][rp->r_month])) {
  1223.                 error("invalid day of month");
  1224.                 return;
  1225.         }
  1226.     }
  1227. }
  1228.  
  1229. static void
  1230. convert(val, buf)
  1231. const long    val;
  1232. char * const    buf;
  1233. {
  1234.     register int    i;
  1235.     register long    shift;
  1236.  
  1237.     for (i = 0, shift = 24; i < 4; ++i, shift -= 8)
  1238.         buf[i] = val >> shift;
  1239. }
  1240.  
  1241. static void
  1242. puttzcode(val, fp)
  1243. const long    val;
  1244. FILE * const    fp;
  1245. {
  1246.     char    buf[4];
  1247.  
  1248.     convert(val, buf);
  1249.     (void) fwrite((genericptr_t) buf,
  1250.         (fwrite_size_t) sizeof buf,
  1251.         (fwrite_size_t) 1, fp);
  1252. }
  1253.  
  1254. static void
  1255. writezone(name)
  1256. const char * const    name;
  1257. {
  1258.     register FILE *        fp;
  1259.     register int        i, j;
  1260.     static char *        fullname;
  1261.     static struct tzhead    tzh;
  1262.  
  1263.     fullname = erealloc(fullname,
  1264.         strlen(directory) + 1 + strlen(name) + 1);
  1265.     (void) sprintf(fullname, "%s/%s", directory, name);
  1266.     if ((fp = fopen(fullname, "wb")) == NULL) {
  1267.         if (mkdirs(fullname) != 0)
  1268.             (void) exit(EXIT_FAILURE);
  1269.         if ((fp = fopen(fullname, "wb")) == NULL) {
  1270.             (void) fprintf(stderr, "%s: Can't create ", progname);
  1271.             (void) perror(fullname);
  1272.             (void) exit(EXIT_FAILURE);
  1273.         }
  1274.     }
  1275.     convert(eitol(typecnt), tzh.tzh_ttisstdcnt);
  1276.     convert(eitol(leapcnt), tzh.tzh_leapcnt);
  1277.     convert(eitol(timecnt), tzh.tzh_timecnt);
  1278.     convert(eitol(typecnt), tzh.tzh_typecnt);
  1279.     convert(eitol(charcnt), tzh.tzh_charcnt);
  1280.     (void) fwrite((genericptr_t) &tzh,
  1281.         (fwrite_size_t) sizeof tzh,
  1282.         (fwrite_size_t) 1, fp);
  1283.     for (i = 0; i < timecnt; ++i) {
  1284.         j = leapcnt;
  1285.         while (--j >= 0)
  1286.             if (ats[i] >= trans[j]) {
  1287.                 ats[i] = tadd(ats[i], corr[j]);
  1288.                 break;
  1289.             }
  1290.         puttzcode((long) ats[i], fp);
  1291.     }
  1292.     if (timecnt > 0)
  1293.         (void) fwrite((genericptr_t) types,
  1294.             (fwrite_size_t) sizeof types[0],
  1295.             (fwrite_size_t) timecnt, fp);
  1296.     for (i = 0; i < typecnt; ++i) {
  1297.         puttzcode((long) gmtoffs[i], fp);
  1298.         (void) putc(isdsts[i], fp);
  1299.         (void) putc(abbrinds[i], fp);
  1300.     }
  1301.     if (charcnt != 0)
  1302.         (void) fwrite((genericptr_t) chars,
  1303.             (fwrite_size_t) sizeof chars[0],
  1304.             (fwrite_size_t) charcnt, fp);
  1305.     for (i = 0; i < leapcnt; ++i) {
  1306.         if (roll[i]) {
  1307.             if (timecnt == 0 || trans[i] < ats[0]) {
  1308.                 j = 0;
  1309.                 while (isdsts[j])
  1310.                     if (++j >= typecnt) {
  1311.                         j = 0;
  1312.                         break;
  1313.                     }
  1314.             } else {
  1315.                 j = 1;
  1316.                 while (j < timecnt && trans[i] >= ats[j])
  1317.                     ++j;
  1318.                 j = types[j - 1];
  1319.             }
  1320.             puttzcode((long) tadd(trans[i], -gmtoffs[j]), fp);
  1321.         } else    puttzcode((long) trans[i], fp);
  1322.         puttzcode((long) corr[i], fp);
  1323.     }
  1324.     for (i = 0; i < typecnt; ++i)
  1325.         (void) putc(ttisstds[i], fp);
  1326.     if (ferror(fp) || fclose(fp)) {
  1327.         (void) fprintf(stderr, "%s: Write error on ", progname);
  1328.         (void) perror(fullname);
  1329.         (void) exit(EXIT_FAILURE);
  1330.     }
  1331. }
  1332.  
  1333. static void
  1334. outzone(zpfirst, zonecount)
  1335. const struct zone * const    zpfirst;
  1336. const int            zonecount;
  1337. {
  1338.     register const struct zone *    zp;
  1339.     register struct rule *        rp;
  1340.     register int            i, j;
  1341.     register int            usestart, useuntil;
  1342.     register time_t            starttime, untiltime;
  1343.     register long            gmtoff;
  1344.     register long            stdoff;
  1345.     register int            year;
  1346.     register long            startoff;
  1347.     register int            startisdst;
  1348.     register int            startttisstd;
  1349.     register int            type;
  1350.     char                startbuf[BUFSIZ];
  1351.  
  1352.     /*
  1353.     ** Now. . .finally. . .generate some useful data!
  1354.     */
  1355.     timecnt = 0;
  1356.     typecnt = 0;
  1357.     charcnt = 0;
  1358.     /*
  1359.     ** A guess that may well be corrected later.
  1360.     */
  1361.     stdoff = 0;
  1362.     /*
  1363.     ** Thanks to Earl Chew (earl@dnd.icp.nec.com.au)
  1364.     ** for noting the need to unconditionally initialize startttisstd.
  1365.     */
  1366.     startttisstd = FALSE;
  1367. #ifdef lint
  1368.     starttime = 0;
  1369. #endif /* defined lint */
  1370.     for (i = 0; i < zonecount; ++i) {
  1371.         zp = &zpfirst[i];
  1372.         usestart = i > 0 && (zp - 1)->z_untiltime > min_time;
  1373.         useuntil = i < (zonecount - 1);
  1374.         if (useuntil && zp->z_untiltime <= min_time)
  1375.             continue;
  1376.         gmtoff = zp->z_gmtoff;
  1377.         eat(zp->z_filename, zp->z_linenum);
  1378.         startisdst = -1;
  1379.         if (zp->z_nrules == 0) {
  1380.             stdoff = zp->z_stdoff;
  1381.             (void) strcpy(startbuf, zp->z_format);
  1382.             type = addtype(oadd(zp->z_gmtoff, stdoff),
  1383.                 startbuf, stdoff != 0, startttisstd);
  1384.             if (usestart)
  1385.                 addtt(starttime, type);
  1386.             else if (stdoff != 0)
  1387.                 addtt(min_time, type);
  1388.         } else for (year = min_year; year <= max_year; ++year) {
  1389.             if (useuntil && year > zp->z_untilrule.r_hiyear)
  1390.                 break;
  1391.             /*
  1392.             ** Mark which rules to do in the current year.
  1393.             ** For those to do, calculate rpytime(rp, year);
  1394.             */
  1395.             for (j = 0; j < zp->z_nrules; ++j) {
  1396.                 rp = &zp->z_rules[j];
  1397.                 eats(zp->z_filename, zp->z_linenum,
  1398.                     rp->r_filename, rp->r_linenum);
  1399.                 rp->r_todo = year >= rp->r_loyear &&
  1400.                         year <= rp->r_hiyear &&
  1401.                         yearistype(year, rp->r_yrtype);
  1402.                 if (rp->r_todo)
  1403.                     rp->r_temp = rpytime(rp, year);
  1404.             }
  1405.             for ( ; ; ) {
  1406.                 register int    k;
  1407.                 register time_t    jtime, ktime;
  1408.                 register long    offset;
  1409.                 char        buf[BUFSIZ];
  1410.  
  1411.                 if (useuntil) {
  1412.                     /*
  1413.                     ** Turn untiltime into GMT
  1414.                     ** assuming the current gmtoff and
  1415.                     ** stdoff values.
  1416.                     */
  1417.                     untiltime = tadd(zp->z_untiltime,
  1418.                         -gmtoff);
  1419.                     if (!zp->z_untilrule.r_todisstd)
  1420.                         untiltime = tadd(untiltime,
  1421.                             -stdoff);
  1422.                 }
  1423.                 /*
  1424.                 ** Find the rule (of those to do, if any)
  1425.                 ** that takes effect earliest in the year.
  1426.                 */
  1427.                 k = -1;
  1428. #ifdef lint
  1429.                 ktime = 0;
  1430. #endif /* defined lint */
  1431.                 for (j = 0; j < zp->z_nrules; ++j) {
  1432.                     rp = &zp->z_rules[j];
  1433.                     if (!rp->r_todo)
  1434.                         continue;
  1435.                     eats(zp->z_filename, zp->z_linenum,
  1436.                         rp->r_filename, rp->r_linenum);
  1437.                     offset = gmtoff;
  1438.                     if (!rp->r_todisstd)
  1439.                         offset = oadd(offset, stdoff);
  1440.                     jtime = rp->r_temp;
  1441.                     if (jtime == min_time ||
  1442.                         jtime == max_time)
  1443.                             continue;
  1444.                     jtime = tadd(jtime, -offset);
  1445.                     if (k < 0 || jtime < ktime) {
  1446.                         k = j;
  1447.                         ktime = jtime;
  1448.                     }
  1449.                 }
  1450.                 if (k < 0)
  1451.                     break;    /* go on to next year */
  1452.                 rp = &zp->z_rules[k];
  1453.                 rp->r_todo = FALSE;
  1454.                 if (useuntil && ktime >= untiltime)
  1455.                     break;
  1456.                 if (usestart) {
  1457.                     if (ktime < starttime) {
  1458.                     stdoff = rp->r_stdoff;
  1459.                     startoff = oadd(zp->z_gmtoff,
  1460.                         rp->r_stdoff);
  1461.                     (void) sprintf(startbuf, zp->z_format,
  1462.                         rp->r_abbrvar);
  1463.                     startisdst = rp->r_stdoff != 0;
  1464.                     continue;
  1465.                     }
  1466.                     usestart = FALSE;
  1467.                     if (ktime != starttime) {
  1468.                     if (startisdst < 0 &&
  1469.                         zp->z_gmtoff !=
  1470.                         (zp - 1)->z_gmtoff) {
  1471.                         type = (timecnt == 0) ? 0 :
  1472.                             types[timecnt - 1];
  1473.                         startoff = oadd(gmtoffs[type],
  1474.                             -(zp - 1)->z_gmtoff);
  1475.                         startisdst = startoff != 0;
  1476.                         startoff = oadd(startoff,
  1477.                             zp->z_gmtoff);
  1478.                         (void) strcpy(startbuf,
  1479.                             &chars[abbrinds[type]]);
  1480.                     }
  1481.                     if (startisdst >= 0)
  1482. addtt(starttime, addtype(startoff, startbuf, startisdst, startttisstd));
  1483.                     }
  1484.                 }
  1485.                 eats(zp->z_filename, zp->z_linenum,
  1486.                     rp->r_filename, rp->r_linenum);
  1487.                 (void) sprintf(buf, zp->z_format,
  1488.                     rp->r_abbrvar);
  1489.                 offset = oadd(zp->z_gmtoff, rp->r_stdoff);
  1490.                 type = addtype(offset, buf, rp->r_stdoff != 0,
  1491.                     rp->r_todisstd);
  1492.                 addtt(ktime, type);
  1493.                 stdoff = rp->r_stdoff;
  1494.             }
  1495.         }
  1496.         /*
  1497.         ** Now we may get to set starttime for the next zone line.
  1498.         */
  1499.         if (useuntil) {
  1500.             starttime = tadd(zp->z_untiltime, -gmtoff);
  1501.             startttisstd = zp->z_untilrule.r_todisstd;
  1502.             if (!startttisstd)
  1503.                 starttime = tadd(starttime, -stdoff);
  1504.         }
  1505.     }
  1506.     writezone(zpfirst->z_name);
  1507. }
  1508.  
  1509. static void
  1510. addtt(starttime, type)
  1511. const time_t    starttime;
  1512. const int    type;
  1513. {
  1514.     if (timecnt != 0 && type == types[timecnt - 1])
  1515.         return;    /* easy enough! */
  1516.     if (timecnt == 0 && type == 0 && isdsts[0] == 0)
  1517.         return; /* handled by default rule */
  1518.     if (timecnt >= TZ_MAX_TIMES) {
  1519.         error("too many transitions?!");
  1520.         (void) exit(EXIT_FAILURE);
  1521.     }
  1522.     ats[timecnt] = starttime;
  1523.     types[timecnt] = type;
  1524.     ++timecnt;
  1525. }
  1526.  
  1527. static int
  1528. addtype(gmtoff, abbr, isdst, ttisstd)
  1529. const long        gmtoff;
  1530. const char * const    abbr;
  1531. const int        isdst;
  1532. const int        ttisstd;
  1533. {
  1534.     register int    i, j;
  1535.  
  1536.     /*
  1537.     ** See if there's already an entry for this zone type.
  1538.     ** If so, just return its index.
  1539.     */
  1540.     for (i = 0; i < typecnt; ++i) {
  1541.         if (gmtoff == gmtoffs[i] && isdst == isdsts[i] &&
  1542.             strcmp(abbr, &chars[abbrinds[i]]) == 0 &&
  1543.             ttisstd == ttisstds[i])
  1544.                 return i;
  1545.     }
  1546.     /*
  1547.     ** There isn't one; add a new one, unless there are already too
  1548.     ** many.
  1549.     */
  1550.     if (typecnt >= TZ_MAX_TYPES) {
  1551.         error("too many local time types");
  1552.         (void) exit(EXIT_FAILURE);
  1553.     }
  1554.     gmtoffs[i] = gmtoff;
  1555.     isdsts[i] = isdst;
  1556.     ttisstds[i] = ttisstd;
  1557.  
  1558.     for (j = 0; j < charcnt; ++j)
  1559.         if (strcmp(&chars[j], abbr) == 0)
  1560.             break;
  1561.     if (j == charcnt)
  1562.         newabbr(abbr);
  1563.     abbrinds[i] = j;
  1564.     ++typecnt;
  1565.     return i;
  1566. }
  1567.  
  1568. static void
  1569. leapadd(t, positive, rolling, count)
  1570. const time_t    t;
  1571. const int    positive;
  1572. const int    rolling;
  1573. int        count;
  1574. {
  1575.     register int    i, j;
  1576.  
  1577.     if (leapcnt + (positive ? count : 1) > TZ_MAX_LEAPS) {
  1578.         error("too many leap seconds");
  1579.         (void) exit(EXIT_FAILURE);
  1580.     }
  1581.     for (i = 0; i < leapcnt; ++i)
  1582.         if (t <= trans[i]) {
  1583.             if (t == trans[i]) {
  1584.                 error("repeated leap second moment");
  1585.                 (void) exit(EXIT_FAILURE);
  1586.             }
  1587.             break;
  1588.         }
  1589.     do {
  1590.         for (j = leapcnt; j > i; --j) {
  1591.             trans[j] = trans[j - 1];
  1592.             corr[j] = corr[j - 1];
  1593.             roll[j] = roll[j - 1];
  1594.         }
  1595.         trans[i] = t;
  1596.         corr[i] = positive ? 1L : eitol(-count);
  1597.         roll[i] = rolling;
  1598.         ++leapcnt;
  1599.     } while (positive && --count != 0);
  1600. }
  1601.  
  1602. static void
  1603. adjleap()
  1604. {
  1605.     register int    i;
  1606.     register long    last = 0;
  1607.  
  1608.     /*
  1609.     ** propagate leap seconds forward
  1610.     */
  1611.     for (i = 0; i < leapcnt; ++i) {
  1612.         trans[i] = tadd(trans[i], last);
  1613.         last = corr[i] += last;
  1614.     }
  1615. }
  1616.  
  1617. static int
  1618. yearistype(year, type)
  1619. const int        year;
  1620. const char * const    type;
  1621. {
  1622.     static char *    buf;
  1623.     int        result;
  1624.  
  1625.     if (type == NULL || *type == '\0')
  1626.         return TRUE;
  1627.     if (strcmp(type, "uspres") == 0)
  1628.         return (year % 4) == 0;
  1629.     if (strcmp(type, "nonpres") == 0)
  1630.         return (year % 4) != 0;
  1631.     buf = erealloc(buf, 132 + strlen(yitcommand) + strlen(type));
  1632.     (void) sprintf(buf, "%s %d %s", yitcommand, year, type);
  1633.     result = system(buf);
  1634.     if (result == 0)
  1635.         return TRUE;
  1636.     if (result == (1 << 8))
  1637.         return FALSE;
  1638.     error("Wild result from command execution");
  1639.     (void) fprintf(stderr, "%s: command was '%s', result was %d\n",
  1640.         progname, buf, result);
  1641.     for ( ; ; )
  1642.         (void) exit(EXIT_FAILURE);
  1643. }
  1644.  
  1645. static int
  1646. lowerit(a)
  1647. const int    a;
  1648. {
  1649.     return (isascii(a) && isupper(a)) ? tolower(a) : a;
  1650. }
  1651.  
  1652. static int
  1653. ciequal(ap, bp)        /* case-insensitive equality */
  1654. register const char *    ap;
  1655. register const char *    bp;
  1656. {
  1657.     while (lowerit(*ap) == lowerit(*bp++))
  1658.         if (*ap++ == '\0')
  1659.             return TRUE;
  1660.     return FALSE;
  1661. }
  1662.  
  1663. static int
  1664. itsabbr(abbr, word)
  1665. register const char *    abbr;
  1666. register const char *    word;
  1667. {
  1668.     if (lowerit(*abbr) != lowerit(*word))
  1669.         return FALSE;
  1670.     ++word;
  1671.     while (*++abbr != '\0')
  1672.         do if (*word == '\0')
  1673.             return FALSE;
  1674.                 while (lowerit(*word++) != lowerit(*abbr));
  1675.     return TRUE;
  1676. }
  1677.  
  1678. static const struct lookup *
  1679. byword(word, table)
  1680. register const char * const        word;
  1681. register const struct lookup * const    table;
  1682. {
  1683.     register const struct lookup *    foundlp;
  1684.     register const struct lookup *    lp;
  1685.  
  1686.     if (word == NULL || table == NULL)
  1687.         return NULL;
  1688.     /*
  1689.     ** Look for exact match.
  1690.     */
  1691.     for (lp = table; lp->l_word != NULL; ++lp)
  1692.         if (ciequal(word, lp->l_word))
  1693.             return lp;
  1694.     /*
  1695.     ** Look for inexact match.
  1696.     */
  1697.     foundlp = NULL;
  1698.     for (lp = table; lp->l_word != NULL; ++lp)
  1699.         if (itsabbr(word, lp->l_word))
  1700.             if (foundlp == NULL)
  1701.                 foundlp = lp;
  1702.             else    return NULL;    /* multiple inexact matches */
  1703.     return foundlp;
  1704. }
  1705.  
  1706. static char **
  1707. getfields(cp)
  1708. register char *    cp;
  1709. {
  1710.     register char *        dp;
  1711.     register char **    array;
  1712.     register int        nsubs;
  1713.  
  1714.     if (cp == NULL)
  1715.         return NULL;
  1716.     array = (char **) emalloc((int) ((strlen(cp) + 1) * sizeof *array));
  1717.     nsubs = 0;
  1718.     for ( ; ; ) {
  1719.         while (isascii(*cp) && isspace(*cp))
  1720.             ++cp;
  1721.         if (*cp == '\0' || *cp == '#')
  1722.             break;
  1723.         array[nsubs++] = dp = cp;
  1724.         do {
  1725.             if ((*dp = *cp++) != '"')
  1726.                 ++dp;
  1727.             else while ((*dp = *cp++) != '"')
  1728.                 if (*dp != '\0')
  1729.                     ++dp;
  1730.                 else    error("Odd number of quotation marks");
  1731.         } while (*cp != '\0' && *cp != '#' &&
  1732.             (!isascii(*cp) || !isspace(*cp)));
  1733.         if (isascii(*cp) && isspace(*cp))
  1734.             ++cp;
  1735.         *dp = '\0';
  1736.     }
  1737.     array[nsubs] = NULL;
  1738.     return array;
  1739. }
  1740.  
  1741. static long
  1742. oadd(t1, t2)
  1743. const long    t1;
  1744. const long    t2;
  1745. {
  1746.     register long    t;
  1747.  
  1748.     t = t1 + t2;
  1749.     if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) {
  1750.         error("time overflow");
  1751.         (void) exit(EXIT_FAILURE);
  1752.     }
  1753.     return t;
  1754. }
  1755.  
  1756. static time_t
  1757. tadd(t1, t2)
  1758. const time_t    t1;
  1759. const long    t2;
  1760. {
  1761.     register time_t    t;
  1762.  
  1763.     if (t1 == max_time && t2 > 0)
  1764.         return max_time;
  1765.     if (t1 == min_time && t2 < 0)
  1766.         return min_time;
  1767.     t = t1 + t2;
  1768.     if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) {
  1769.         error("time overflow");
  1770.         (void) exit(EXIT_FAILURE);
  1771.     }
  1772.     return t;
  1773. }
  1774.  
  1775. /*
  1776. ** Given a rule, and a year, compute the date - in seconds since January 1,
  1777. ** 1970, 00:00 LOCAL time - in that year that the rule refers to.
  1778. */
  1779.  
  1780. static time_t
  1781. rpytime(rp, wantedy)
  1782. register const struct rule * const    rp;
  1783. register const int            wantedy;
  1784. {
  1785.     register int    y, m, i;
  1786.     register long    dayoff;            /* with a nod to Margaret O. */
  1787.     register time_t    t;
  1788.  
  1789.     if (wantedy == min_int)
  1790.         return min_time;
  1791.     if (wantedy == max_int)
  1792.         return max_time;
  1793.     dayoff = 0;
  1794.     m = TM_JANUARY;
  1795.     y = EPOCH_YEAR;
  1796.     while (wantedy != y) {
  1797.         if (wantedy > y) {
  1798.             i = len_years[isleap(y)];
  1799.             ++y;
  1800.         } else {
  1801.             --y;
  1802.             i = -len_years[isleap(y)];
  1803.         }
  1804.         dayoff = oadd(dayoff, eitol(i));
  1805.     }
  1806.     while (m != rp->r_month) {
  1807.         i = len_months[isleap(y)][m];
  1808.         dayoff = oadd(dayoff, eitol(i));
  1809.         ++m;
  1810.     }
  1811.     i = rp->r_dayofmonth;
  1812.     if (m == TM_FEBRUARY && i == 29 && !isleap(y)) {
  1813.         if (rp->r_dycode == DC_DOWLEQ)
  1814.             --i;
  1815.         else {
  1816.             error("use of 2/29 in non leap-year");
  1817.             (void) exit(EXIT_FAILURE);
  1818.         }
  1819.     }
  1820.     --i;
  1821.     dayoff = oadd(dayoff, eitol(i));
  1822.     if (rp->r_dycode == DC_DOWGEQ || rp->r_dycode == DC_DOWLEQ) {
  1823.         register long    wday;
  1824.  
  1825. #define LDAYSPERWEEK    ((long) DAYSPERWEEK)
  1826.         wday = eitol(EPOCH_WDAY);
  1827.         /*
  1828.         ** Don't trust mod of negative numbers.
  1829.         */
  1830.         if (dayoff >= 0)
  1831.             wday = (wday + dayoff) % LDAYSPERWEEK;
  1832.         else {
  1833.             wday -= ((-dayoff) % LDAYSPERWEEK);
  1834.             if (wday < 0)
  1835.                 wday += LDAYSPERWEEK;
  1836.         }
  1837.         while (wday != eitol(rp->r_wday))
  1838.             if (rp->r_dycode == DC_DOWGEQ) {
  1839.                 dayoff = oadd(dayoff, (long) 1);
  1840.                 if (++wday >= LDAYSPERWEEK)
  1841.                     wday = 0;
  1842.                 ++i;
  1843.             } else {
  1844.                 dayoff = oadd(dayoff, (long) -1);
  1845.                 if (--wday < 0)
  1846.                     wday = LDAYSPERWEEK - 1;
  1847.                 --i;
  1848.             }
  1849.         if (i < 0 || i >= len_months[isleap(y)][m]) {
  1850.             error("no day in month matches rule");
  1851.             (void) exit(EXIT_FAILURE);
  1852.         }
  1853.     }
  1854.     if (dayoff < 0 && !tt_signed)
  1855.         return min_time;
  1856.     t = (time_t) dayoff * SECSPERDAY;
  1857.     /*
  1858.     ** Cheap overflow check.
  1859.     */
  1860.     if (t / SECSPERDAY != dayoff)
  1861.         return (dayoff > 0) ? max_time : min_time;
  1862.     return tadd(t, rp->r_tod);
  1863. }
  1864.  
  1865. static void
  1866. newabbr(string)
  1867. const char * const    string;
  1868. {
  1869.     register int    i;
  1870.  
  1871.     i = strlen(string) + 1;
  1872.     if (charcnt + i > TZ_MAX_CHARS) {
  1873.         error("too many, or too long, time zone abbreviations");
  1874.         (void) exit(EXIT_FAILURE);
  1875.     }
  1876.     (void) strcpy(&chars[charcnt], string);
  1877.     charcnt += eitol(i);
  1878. }
  1879.  
  1880. static int
  1881. mkdirs(argname)
  1882. char * const    argname;
  1883. {
  1884.     register char *    name;
  1885.     register char *    cp;
  1886.  
  1887.     if (argname == NULL || *argname == '\0')
  1888.         return 0;
  1889.     cp = name = ecpyalloc(argname);
  1890.     while ((cp = strchr(cp + 1, '/')) != 0) {
  1891.         *cp = '\0';
  1892. #ifndef unix
  1893.         /*
  1894.         ** MS-DOS drive specifier?
  1895.         */
  1896.         if (strlen(name) == 2 && isascii(name[0]) &&
  1897.             isalpha(name[0]) && name[1] == ':') {
  1898.                 *cp = '/';
  1899.                 continue;
  1900.         }
  1901. #endif /* !defined unix */
  1902.         if (!itsdir(name)) {
  1903.             /*
  1904.             ** It doesn't seem to exist, so we try to create it.
  1905.             */
  1906.             if (emkdir(name, 0755) != 0) {
  1907.                 (void) fprintf(stderr,
  1908.                     "%s: Can't create directory ",
  1909.                     progname);
  1910.                 (void) perror(name);
  1911.                 ifree(name);
  1912.                 return -1;
  1913.             }
  1914.         }
  1915.         *cp = '/';
  1916.     }
  1917.     ifree(name);
  1918.     return 0;
  1919. }
  1920.  
  1921. static long
  1922. eitol(i)
  1923. const int    i;
  1924. {
  1925.     long    l;
  1926.  
  1927.     l = i;
  1928.     if ((i < 0 && l >= 0) || (i == 0 && l != 0) || (i > 0 && l <= 0)) {
  1929.         (void) fprintf(stderr,
  1930.             "%s: %d did not sign extend correctly\n",
  1931.             progname, i);
  1932.         (void) exit(EXIT_FAILURE);
  1933.     }
  1934.     return l;
  1935. }
  1936.  
  1937. /*
  1938. ** UNIX is a registered trademark of AT&T.
  1939. */
  1940.